#ifndef __AVI_H
#define __AVI_H

#include "sys_uart.h"
#define avi_sysprintf sysprintf

#ifndef u32
#define u32 unsigned int
#endif

#ifndef u16
#define u16 unsigned short
#endif

#ifndef u8
#define u8 unsigned char
#endif

// 错误类型
typedef enum
{
	AVI_OK = 0,		// 0,成功
	AVI_RIFF_ERR,	// 1,RIFF ID读取失败
	AVI_AVI_ERR,	// 2,AVI ID读取失败
	AVI_LIST_ERR,	// 3,LIST ID读取失败
	AVI_HDRL_ERR,	// 4,HDRL ID读取失败
	AVI_AVIH_ERR,	// 5,AVIH ID读取失败
	AVI_STRL_ERR,	// 6,STRL ID读取失败
	AVI_STRH_ERR,	// 7,STRH ID读取失败
	AVI_STRF_ERR,	// 8,STRF ID读取失败
	AVI_MOVI_ERR,	// 9,MOVI ID读取失败
	AVI_FORMAT_ERR, // 10,格式错误
	AVI_STREAM_ERR, // 11,流错误
} AVISTATUS;

#define AVI_RIFF_ID 0X46464952
#define AVI_AVI_ID 0X20495641
#define AVI_LIST_ID 0X5453494C
#define AVI_HDRL_ID 0X6C726468 // 信息块标志
#define AVI_MOVI_ID 0X69766F6D // 数据块标志
#define AVI_STRL_ID 0X6C727473 // strl标志

#define AVI_AVIH_ID 0X68697661 // avih子块∈AVI_HDRL_ID
#define AVI_STRH_ID 0X68727473 // strh(流头)子块∈AVI_STRL_ID
#define AVI_STRF_ID 0X66727473 // strf(流格式)子块∈AVI_STRL_ID
#define AVI_STRD_ID 0X64727473 // strd子块∈AVI_STRL_ID (可选的)

#define AVI_VIDS_STREAM 0X73646976 // 视频流
#define AVI_AUDS_STREAM 0X73647561 // 音频流

#define AVI_VIDS_FLAG 0X6463 // 视频流标志
#define AVI_AUDS_FLAG 0X7762 // 音频流标志
//////////////////////////////////////////////////////////////////////////////////////////

#define AVI_FORMAT_MJPG 0X47504A4D

// AVI 信息结构体
// 将一些重要的数据,存放在这里,方便解码
typedef __packed struct
{
	u32 SecPerFrame;  // 视频帧间隔时间(单位为us)
	u32 TotalFrame;	  // 文件总帧数
	u32 Width;		  // 图像宽
	u32 Height;		  // 图像高
	u32 SampleRate;	  // 音频采样率
	u16 Channels;	  // 声道数,一般为2,表示立体声
	u16 AudioBufSize; // 音频缓冲区大小
	u16 AudioType;	  // 音频类型:0X0001=PCM;0X0050=MP2;0X0055=MP3;0X2000=AC3;
	u16 StreamID;	  // 流类型ID,StreamID=='dc'==0X6463 /StreamID=='wb'==0X7762
	u32 StreamSize;	  // 流大小,必须是偶数,如果读取到为奇数,则加1.补为偶数.
	u8 *VideoFLAG;	  // 视频帧标记,VideoFLAG="00dc"/"01dc"
	u8 *AudioFLAG;	  // 音频帧标记,AudioFLAG="00wb"/"01wb"
} AVI_INFO;

extern AVI_INFO avix; // avi文件相关信息

//////////////////////////////////////////////////////////////////////////////////////////
// AVI 块信息
typedef struct
{
	u32 RiffID;	  // RiffID=='RIFF'==0X61766968
	u32 FileSize; // AVI文件大小(不包含最初的8字节,也RIFFID和FileSize不计算在内)
	u32 AviID;	  // AviID=='AVI '==0X41564920
} AVI_HEADER;

// AVI 块信息
typedef struct
{
	u32 FrameID;   // 帧ID,FrameID=='RIFF'==0X61766968
	u32 FrameSize; // 帧大小
} FRAME_HEADER;

// LIST 块信息
typedef struct
{
	u32 ListID;	   // ListID=='LIST'==0X4c495354
	u32 BlockSize; // 块大小(不包含最初的8字节,也ListID和BlockSize不计算在内)
	u32 ListType;  // LIST子块类型:hdrl(信息块)/movi(数据块)/idxl(索引块,非必须,是可选的)
} LIST_HEADER;

// avih 子块信息
typedef struct
{
	u32 BlockID;			// 块标志:avih==0X61766968
	u32 BlockSize;			// 块大小(不包含最初的8字节,也就是BlockID和BlockSize不计算在内)
	u32 SecPerFrame;		// 视频帧间隔时间(单位为us)
	u32 MaxByteSec;			// 最大数据传输率,字节/秒
	u32 PaddingGranularity; // 数据填充的粒度
	u32 Flags;				// AVI文件的全局标记，比如是否含有索引块等
	u32 TotalFrame;			// 文件总帧数
	u32 InitFrames;			// 为交互格式指定初始帧数（非交互格式应该指定为0）
	u32 Streams;			// 包含的数据流种类个数,通常为2
	u32 RefBufSize;			// 建议读取本文件的缓存大小（应能容纳最大的块）默认可能是1M字节!!!
	u32 Width;				// 图像宽
	u32 Height;				// 图像高
	u32 Reserved[4];		// 保留
} AVIH_HEADER;

// strh 流头子块信息(strh∈strl)
typedef struct
{
	u32 BlockID;	// 块标志:strh==0X73747268
	u32 BlockSize;	// 块大小(不包含最初的8字节,也就是BlockID和BlockSize不计算在内)
	u32 StreamType; // 数据流种类，vids(0X73646976):视频;auds(0X73647561):音频
	u32 Handler;	// 指定流的处理者，对于音视频来说就是解码器,比如MJPG/H264之类的.
	u32 Flags;		// 标记：是否允许这个流输出？调色板是否变化？
	u16 Priority;	// 流的优先级（当有多个相同类型的流时优先级最高的为默认流）
	u16 Language;	// 音频的语言代号
	u32 InitFrames; // 为交互格式指定初始帧数
	u32 Scale;		// 数据量, 视频每桢的大小或者音频的采样大小
	u32 Rate;		// Scale/Rate=每秒采样数
	u32 Start;		// 数据流开始播放的位置，单位为Scale
	u32 Length;		// 数据流的数据量，单位为Scale
	u32 RefBufSize; // 建议使用的缓冲区大小
	u32 Quality;	// 解压缩质量参数，值越大，质量越好
	u32 SampleSize; // 音频的样本大小
	struct			// 视频帧所占的矩形
	{
		short Left;
		short Top;
		short Right;
		short Bottom;
	} Frame;
} STRH_HEADER;

// BMP结构体
typedef struct
{
	u32 BmpSize;	   // bmp结构体大小,包含(BmpSize在内)
	long Width;		   // 图像宽
	long Height;	   // 图像高
	u16 Planes;		   // 平面数，必须为1
	u16 BitCount;	   // 像素位数,0X0018表示24位
	u32 Compression;   // 压缩类型，比如:MJPG/H264等
	u32 SizeImage;	   // 图像大小
	long XpixPerMeter; // 水平分辨率
	long YpixPerMeter; // 垂直分辨率
	u32 ClrUsed;	   // 实际使用了调色板中的颜色数,压缩格式中不使用
	u32 ClrImportant;  // 重要的颜色
} BMP_HEADER;

// 颜色表
typedef struct
{
	u8 rgbBlue;		// 蓝色的亮度(值范围为0-255)
	u8 rgbGreen;	// 绿色的亮度(值范围为0-255)
	u8 rgbRed;		// 红色的亮度(值范围为0-255)
	u8 rgbReserved; // 保留，必须为0
} AVIRGBQUAD;

// 对于strh,如果是视频流,strf(流格式)使STRH_BMPHEADER块
typedef struct
{
	u32 BlockID;			// 块标志,strf==0X73747266
	u32 BlockSize;			// 块大小(不包含最初的8字节,也就是BlockID和本BlockSize不计算在内)
	BMP_HEADER bmiHeader;	// 位图信息头
	AVIRGBQUAD bmColors[1]; // 颜色表
} STRF_BMPHEADER;

// 对于strh,如果是音频流,strf(流格式)使STRH_WAVHEADER块
typedef struct
{
	u32 BlockID;	// 块标志,strf==0X73747266
	u32 BlockSize;	// 块大小(不包含最初的8字节,也就是BlockID和本BlockSize不计算在内)
	u16 FormatTag;	// 格式标志:0X0001=PCM,0X0055=MP3...
	u16 Channels;	// 声道数,一般为2,表示立体声
	u32 SampleRate; // 音频采样率
	u32 BaudRate;	// 波特率
	u16 BlockAlign; // 数据块对齐标志
	u16 Size;		// 该结构大小
} STRF_WAVHEADER;

#define MAKEWORD(ptr) (u16)(((u16) * ((u8 *)(ptr)) << 8) | (u16) * (u8 *)((ptr) + 1))
#define MAKEDWORD(ptr) (u32)(((u16) * (u8 *)(ptr) | (((u16) * (u8 *)(ptr + 1)) << 8) | \
							  (((u16) * (u8 *)(ptr + 2)) << 16) | (((u16) * (u8 *)(ptr + 3)) << 24)))

AVISTATUS avi_init(u8 *buf, u32 size);		  // 初始化avi解码器
u16 avi_srarch_id(u8 *buf, u32 size, u8 *id); // 查找ID,ID必须是4个字节长度
AVISTATUS avi_get_streaminfo(u8 *buf);		  // 获取流信息

u8 Avih_Parser(u8 *buffer);
u8 Strl_Parser(u8 *buffer);
u8 Strf_Parser(u8 *buffer);

u16 Search_Movi(u8 *buffer);
u16 Search_Fram(u8 *buffer);
u32 ReadUnit(u8 *buffer, u8 index, u8 Bytes, u8 Format);

#endif
